/**
 * @file 应用入口文件
 * @description 初始化NestJS应用并配置全局中间件
 * @author GPS轨迹可视化系统
 * @date 2024-02-26
 */

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as dotenv from 'dotenv';
import { IoAdapter } from '@nestjs/platform-socket.io';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
import { TransformInterceptor } from './common/interceptors/transform.interceptor';
import { envConfig } from './config/env.config';
import { json, urlencoded } from 'express';
import { LoggerService } from './common/services/logger.service';
import { EventEmitter } from 'events';

// 加载环境变量
dotenv.config();

// 获取命令开始的时间戳（从环境变量）
let commandStartTime = Date.now();
if (process.env.NEST_START_TIME) {
  try {
    // 转换为毫秒
    commandStartTime = parseInt(process.env.NEST_START_TIME) * 1000;
  } catch (e) {
    console.error('无法解析NEST_START_TIME环境变量');
  }
}

// 计算编译耗时（从命令执行到main.ts运行）
const compilationTime = Date.now() - commandStartTime;
// 标记是否已经输出完成时间
let hasLoggedCompletion = false;
// 全局事件总线
const globalEventEmitter = new EventEmitter();

// 记录编译时间（但不立即显示总时间）
const startTimeStr = new Date(commandStartTime).toLocaleTimeString();
console.log(`\n[计时器] ⏱️ 命令执行时间: ${startTimeStr}`);
console.log(`[计时器] 🔄 编译完成: ${(compilationTime/1000).toFixed(2)}秒`);

/**
 * 自定义WebSocket适配器类
 * @description 扩展NestJS的IoAdapter，添加CORS和其他WebSocket配置
 */
class CustomIoAdapter extends IoAdapter {
  /**
   * 创建IO服务器
   * @param port 端口号
   * @param options 可选配置项
   * @returns 配置好的IO服务器实例
   */
  createIOServer(port: number, options?: any) {
    const server = super.createIOServer(port, {
      ...options,
      cors: {
        origin: ['http://localhost:3000', 'http://localhost:5173', 'http://localhost:3002', 'http://localhost:8080'],
        methods: ['GET', 'POST', 'OPTIONS'],
        credentials: true,
        allowedHeaders: [
          'Content-Type',
          'Authorization',
          'X-Requested-With',
          'Accept',
          'Origin',
          'Access-Control-Allow-Origin',
          'Access-Control-Allow-Credentials',
          'Access-Control-Allow-Headers'
        ],
        exposedHeaders: [
          'Access-Control-Allow-Origin',
          'Access-Control-Allow-Credentials'
        ]
      },
      allowEIO3: true,
      transports: ['websocket', 'polling'],
      pingTimeout: 60000,
      pingInterval: 25000,
      upgradeTimeout: 10000,
      maxHttpBufferSize: 1e8,
      allowUpgrades: true,
    });
    return server;
  }
}

/**
 * 应用引导函数
 * @description 配置并启动NestJS应用
 * @returns Promise<void>
 */
async function bootstrap() {
  // 创建Nest应用实例 - 优化日志级别配置，减少启动时的日志输出
  const app = await NestFactory.create(AppModule, {
    // 只记录警告和错误级别的日志，关闭普通日志，加快启动速度
    logger: ['error', 'warn']
  });
  
  // 配置跨域
  app.enableCors({
    origin: ['http://localhost:3000', 'http://localhost:5173', 'http://localhost:3002', 'http://localhost:8080'],
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
    credentials: true,
    allowedHeaders: [
      'Content-Type',
      'Authorization',
      'X-Requested-With',
      'Accept',
      'Origin',
      'Access-Control-Allow-Origin',
      'Access-Control-Allow-Credentials',
      'Access-Control-Allow-Headers'
    ],
    exposedHeaders: [
      'Access-Control-Allow-Origin',
      'Access-Control-Allow-Credentials'
    ]
  });

  // 应用启动后再延迟进行更多的配置，先确保核心功能启动
  setTimeout(() => {
    // 配置WebSocket适配器
    app.useWebSocketAdapter(new CustomIoAdapter(app));
    
    // 注册全局过滤器
    app.useGlobalFilters(new HttpExceptionFilter());
    
    // 注册全局响应转换拦截器
    app.useGlobalInterceptors(new TransformInterceptor());
    
    console.log('非核心配置已完成加载');
  }, 100);

  // 配置全局前缀
  app.setGlobalPrefix('api');

  // 获取配置的主机和端口
  const host = envConfig.server.host;
  const port = envConfig.server.port;

  // 启动服务器
  await app.listen(port, host);
  console.log(`服务已启动: http://${host}:${port}`);
  
  const httpStartTime = Date.now();
  console.log(`[计时器] 🌐 HTTP服务器启动: ${((httpStartTime - commandStartTime)/1000).toFixed(2)}秒`);
  
  // 如果30秒内没有检测到MongoDB连接，强制输出完成时间
  setTimeout(() => {
    if (!hasLoggedCompletion) {
      logCompletionTime('(未检测到MongoDB连接成功事件)');
    }
  }, 30000);
}

// 记录完成时间的函数
function logCompletionTime(note: string = '') {
  if (hasLoggedCompletion) return;
  hasLoggedCompletion = true;
  
  const endTime = Date.now();
  const totalTime = endTime - commandStartTime;
  const initTime = totalTime - compilationTime;
  
  console.log(`\n[计时器] ⏱️ 启动完成: ${new Date().toLocaleTimeString()} ${note}`);
  console.log(`[计时器] ⏱️ 总耗时: ${(totalTime/1000).toFixed(2)}秒`);
  console.log(`[计时器] 📊 性能分析:`);
  console.log(`  - 编译阶段: ${(compilationTime/1000).toFixed(2)}秒 (${Math.round(compilationTime/totalTime*100)}%)`);
  console.log(`  - 初始化阶段: ${(initTime/1000).toFixed(2)}秒 (${Math.round(initTime/totalTime*100)}%)\n`);
}

// 监听MongoDB连接事件
globalEventEmitter.once('mongoConnected', () => {
  logCompletionTime('(MongoDB连接成功)');
});

// 修补原生EventEmitter.emit，捕获MongoDB连接事件
const originalEmit = EventEmitter.prototype.emit;
EventEmitter.prototype.emit = function(event: string, ...args: any[]) {
  const result = originalEmit.apply(this, [event, ...args]);
  
  // 检测MongoDB连接成功的日志事件
  if (args.length > 0 && 
     typeof args[0] === 'object' && 
     args[0] !== null &&
     'context' in args[0] && 
     args[0].context === 'GpsLogRepository' && 
     'message' in args[0] && 
     typeof args[0].message === 'string' &&
     args[0].message.includes('MongoDB连接成功')) {
    setTimeout(() => globalEventEmitter.emit('mongoConnected'), 10);
  }
  
  return result;
};

bootstrap(); 